package cn.assumejson.springframework.aop.framework.autoproxy;

import cn.assumejson.springframework.aop.Advisor;
import cn.assumejson.springframework.aop.PointcutAdvisor;
import cn.assumejson.springframework.aop.TargetSource;
import cn.assumejson.springframework.aop.config.AopConfigUtils;
import cn.assumejson.springframework.aop.framework.BeanFactoryAdvisorRetrievalHelper;
import cn.assumejson.springframework.beans.context.support.AopUtils;
import cn.assumejson.springframework.beans.factory.BeanFactory;
import cn.assumejson.springframework.beans.factory.BeansException;
import cn.assumejson.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import cn.assumejson.springframework.beans.factory.support.DefaultListableBeanFactory;

import java.util.Collection;
import java.util.List;

/**
 * 操作 advisor
 *
 * @author Mr. Li
 * @version 1.0
 * @since 1.0 2021/12/2 17:34
 */
public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator {

    private BeanFactoryAdvisorRetrievalHelper advisorRetrievalHelper;

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        super.setBeanFactory(beanFactory);
        // 初始化AOP工厂类
        initBeanFactory((ConfigurableListableBeanFactory) beanFactory);
    }

    protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        this.advisorRetrievalHelper = new BeanFactoryAdvisorRetrievalHelperAdapter(beanFactory);
    }

    protected boolean isEligibleAdvisorBean(String beanName) {
        return true;
    }

    @Override
    protected Object[] getAdvicesAndAdvisorsForBean(
            Class<?> beanClass, String beanName, TargetSource targetSource) {
        /**
         * 找到和当前bean匹配的advisor
         */
        List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
        // 获取所有的需要代理对象，进行提前初始化
//        Collection<PointcutAdvisor> advisors =
//                ((DefaultListableBeanFactory) getBeanFactory()).getBeansOfType(PointcutAdvisor.class).values();
        // 如果没找到 不创建代理
        if (advisors.isEmpty()) {
            return DO_NOT_PROXY;
        }
        return advisors.toArray();
    }

    private List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
        // 找到所有的Advisor
        List<Advisor> candidateAdvisors = findCandidateAdvisors();

        // 进行筛选
        return findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
    }

    private List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
        if (candidateAdvisors.isEmpty()) {
            return candidateAdvisors;
        }
        // 遍历所有的Advisors
        return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
    }

    protected List<Advisor> findCandidateAdvisors() {

        return this.advisorRetrievalHelper.findAdvisorBeans();
    }

    private class BeanFactoryAdvisorRetrievalHelperAdapter extends BeanFactoryAdvisorRetrievalHelper {

        public BeanFactoryAdvisorRetrievalHelperAdapter(ConfigurableListableBeanFactory beanFactory) {
            super(beanFactory);
        }

        @Override
        protected boolean isEligibleBean(String beanName) {
            return AbstractAdvisorAutoProxyCreator.this.isEligibleAdvisorBean(beanName);
        }
    }
}
